/**
 * 获取字符url查询数据
 * 参数 [url] 没有参数使用当前url进行解析，有参数时解析的为给出的参数
 * 返回值 {object} 返回一个查询字符串解析的key，value对对象，没有则返回空对象
 */
export const urlParse = (search = "") => {
  const obj = {};
  const searchReg = /[?&]?\w+=[^?&#]+/g;
  const res = search.match(searchReg) || [];
  res.forEach((kv) => {
    const [key, val] = kv.substr(1).split("=");
    obj[key] = val;
  });
  return obj;
};

export const queryString = (query = {}) =>
  Object.keys(query)
    .reduce((strArr, key) => strArr.concat([`${key}=${query[key]}`]), [])
    .join('&');


import { divide, multiply } from 'lodash'

/**
 * 驼峰命名转下划线
 * @param obj
 */
export function camel2Underscore (obj = {}) {
  const result = {}

  for (const key in obj) {
    // eslint-disable-next-line no-prototype-builtins
    if (obj.hasOwnProperty(key)) {
      const newKey = key.replace(/([A-Z])/g, '_$1').toLowerCase()
      result[newKey] = obj[key]
    }
  }
  return result
}

// 下划线转驼峰
export const underScoreTurnHump = (params = {}) => Object.keys(params).map(key => {
  const value = params[key]
  const keySplit = key.split('_')
  const newKey = keySplit.reduce((k1, k2) => {
    let ks = [k1]
    if (k2) ks = ks.concat([k2.slice(0,1).toUpperCase(), k2.slice(1).toLowerCase()])
    return ks.join('')
  })
  return { [newKey]: value }
}).reduce((obj, item) => ({ ...obj, ...item }), {})


/**
 * 价格转换， 分转元
 * @param n
 */
export function fractional2Yuan (n = 0) {
  return divide(parseFloat(n), 100).toFixed(2)
}

/**
 * 价格转换: 元转分
 * @param n
 */
export function yuan2Fractional (n = 0) {
  return multiply(parseFloat(n), 100)
}


/**
 * 日期格式化
 * @param date
 * @param fmt
 */
export function formatDate (date, fmt) {
  if (!date) return ''
  const time = new Date(date)
  const v = {
    m: time.getMonth() + 1,
    d: time.getDate(),
    h: time.getHours(),
    i: time.getMinutes(),
    s: time.getSeconds(),
    S: time.getMilliseconds()
  }
  if (new RegExp(/(y+)/).test(fmt)) {
    fmt = fmt.replace(RegExp.$1, (`${time.getFullYear()}`).slice(4 - RegExp.$1.length))
  }
  Object.keys(v).forEach((key) => {
    if (new RegExp(`(${key}+)`).test(fmt)) {
      fmt = fmt.replace(RegExp.$1, `${v[key]}`.length === 1 ? `0${v[key]}` : `${v[key]}`)
    }
  })
  return fmt
}

/**
 * 获取前一天时间戳
 */
export const getTimestampForPreDay = () => +new Date() - 24 * 60 * 60 * 1000
/**
 * 获取后一天时间戳
 */
export const getTimestampForNextDay = () => +new Date() + 24 * 60 * 60 * 1000

/**
 * 获取今日零点时间戳
 */
export const getTimestampForZeroPoint = () => new Date(new Date().toLocaleDateString()).getTime()

/**
 * 获取今日最晚时间 23:59:59的时间戳
 */
export const getTimestampForTodayLastTime = () => new Date(new Date().toLocaleDateString()).getTime()+24 * 60 * 60 * 1000 - 1

/**
 * 获取当前时间的n天后的时间戳
 * @param {number} n 天数
 * @returns {Number} 返回值为时间毫秒值
 */
export const getNextTimes = (n) => +new Date() + n * 86400000

/***
 * 返回本周第一天的时间
 * @return {*} WeekFirstDay 返回本周第一天的时间
 */
export function getWeekFirstDay () {
  const nowDate = new Date()
  return new Date(+nowDate - (nowDate.getDay() - 1) * 86400000)
}

/**
 * 返回本周最后一天的时间
 * @return {*} WeekLastDay 返回本周最后一天的时间
 */
export function getWeekLastDay () {
  const nowDate = new Date()
  const weekFirstDay = new Date(+nowDate - ( nowDate.getDay() - 1) * 86400000)
  return new Date((+weekFirstDay / 1000 + 6 * 86400) * 1000)
}

/**
 * 返回本月第一天的时间
 *  @return {*} MonthFirstDay 返回本月第一天的时间
 */
export function getMonthFirstDay () {
  const nowDate = new Date()
  return new Date(nowDate.getFullYear(), nowDate.getMonth());
}

/**
 *  @return {*} MonthLastDay 返回本月最后一天的时间
 */
export function getMonthLastDay () {
  const nowDate = new Date()
  const monthNextFirstDay = new Date(nowDate.getFullYear(),nowDate.getMonth() + 1)
  return new Date(+monthNextFirstDay - 86400000)
}

export const toString = (obj) => ({}).toString.call(obj)

export const isStr = (str) => toString(str) === '[object String]'

export const isNum = (num) => toString(num) === '[object Number]'

export const isDate = (date) => toString(date) === '[object Date]'

export const isReg = (date) => toString(date) === '[object RegExp]'

export const isFun = (date) => toString(date) === '[object Function]'

export const isBool = (date) => toString(date) === '[object Boolean]'

export const isNull = (obj) => toString(obj) === '[object Null]'

export const isUndefined = (obj) => toString(obj) === '[object Undefined]'

export const isArray = (arr) => toString(arr) === '[object Array]'

export const isEmptyArray = (arr) => isArray(arr) && arr.length === 0

export const isEmptyObj = (obj) => toString(obj) === '[object Object]' && Object.keys(obj).length === 0


export const isEmptyStr = (str) => isStr(str) && str.trim() === ''


/**
 * 是否是无效数据
 * 指(空白字符串，undefined，空数组，空对象，null，NaN)等对象判断为无效数据
 * @param obj
 * @returns {boolean|boolean}
 */
export function isInvalidData (obj) {
  return isEmptyStr(obj) || isUndefined(obj) || isEmptyArray(obj) || isEmptyObj(obj) || isNull(obj) || (isNum(obj) && isNaN(obj))
}



/**
 * 加锁包装函数(与防抖和节流函数类似)
 * 当有方法同时多次调用，但是只希望在该方法第一次调用完成后才能再次调用，可以使用此包装函数
 * @param func Function 传入函数
 * @param onLockFunc Function 当被锁函数没运行完成时触发的函数
 * @return {Function}
 */
export const lockWrap = (func, onLockFunc) => {
  let lock = false
  return async function handler(...args) {
    if (!lock) {
      lock = true
      const result = await func.apply(this, args)
      lock = false
      return result
    }
    onLockFunc && onLockFunc.call(this)
  }
}

// 对比两个json对象是否相等
export const isJsonObjectsEqual = (obj1, obj2) => {
  // 如果两者都是null或者undefined，那么它们是相等的
  if (obj1 === obj2) return true;

  // 如果两者类型不同，那么它们是不相等的
  if (typeof obj1 !== typeof obj2) return false;

  // 如果两者都是对象或数组
  if (typeof obj1 === 'object' && obj1 !== null && obj2 !== null) {
    // 检查键的数量是否相等
    const keys1 = Object.keys(obj1);
    const keys2 = Object.keys(obj2);
    if (keys1.length !== keys2.length) return false;

    // 递归比较每个键的值
    for (let key of keys1) {
      if (!isJsonObjectsEqual(obj1[key], obj2[key])) return false;
    }

    return true;
  }

  // 其他类型的简单值直接比较
  return obj1 === obj2;
}

// 将接受success、fail和complete回调函数，修改成promisify函数
export const promisify = api => (options = {}) => new Promise((resolve, reject) => {
  options.success = function(res) {
    resolve(res)
  }
  options.fail = function(err) {
    reject(err)
  }

  // 如果有complete回调，保留并执行
  const originalComplete = options.complete
  options.complete = function(res) {
    if (originalComplete) {
      originalComplete(res)
    }
    // 注意：complete无论成功或失败都会调用，所以在这里不进行resolve或reject操作
  }

  api(options)
})

// 从一URL中获取文件名
export function getFileNameFromURL(url) {
  const startIndex = url.lastIndexOf('/') + 1
  const endIndex = url.indexOf('?')
  const fileName = url.substring(startIndex, endIndex !== -1 ? endIndex : undefined)
  return fileName
}

// 获取文件名和拓展名
export function getFileNameAndExtension(fileName) {
  const lastDotIndex = fileName.lastIndexOf('.')
  const name = fileName.substring(0, lastDotIndex)
  const extension = fileName.substring(lastDotIndex + 1)
  return { name, extension }
}
